using System;

namespace RapidHDL 
{
	/// <summary>
	/// Summary description for NodeVector.
	/// </summary>
	public class NodeVector
	{
		NodeStructure eNodeStructure;
		System.Collections.ArrayList oNodes;
		int iSize;
		Component oParentComponent;
		NodeFlowType eNodeFlowType;
		string sName;

		public NodeVector(Component poParentComponent, string psName, int piSize)
			: this(poParentComponent,psName,piSize,NodeFlowType.Passthrough)
		{
		}

		public NodeVector(Component poParentComponent, string psName, int piSize, NodeFlowType peNodeFlowType)
		{
			int iIndex;
			Node ndNode;

			oParentComponent = poParentComponent;
			iSize = piSize;
			eNodeFlowType = peNodeFlowType;
			sName = psName;

			oNodes = new System.Collections.ArrayList(piSize);

			for(iIndex = 0; iIndex < iSize; iIndex++)
			{
				ndNode = new Node(this,iIndex);
				oNodes.Add(ndNode);
			}
			
			poParentComponent.NodeVectors.Add(psName,this);
			eNodeStructure = NodeStructure.Unknown;
		}

		public NodeFlowType NodeFlowType 
		{
			set {eNodeFlowType = value;}
			get{return eNodeFlowType;}
		}

		public string Name
		{
			get{return sName;}
		}

		public int Size
		{
			get{return iSize;}
		}
		
		public Node this[int piIndex]
		{
			get{return (Node)oNodes[piIndex];}
			set
			{
				ConnectNode(piIndex,value);
			}
		}

		public System.Collections.ArrayList Nodes
		{
			get{return oNodes;}
			set
			{
				foreach(Node oConnectNode in value)
				{
					ConnectNode(oConnectNode.Position,oConnectNode);
				}
			}
		}

		public NodeVector Connection
		{
			set
			{
				ConnectNodeVector(value);
			}
		}

		public Component ParentComponent
		{
			get{return oParentComponent;}
		}

		public void Resize()
		{
		}

		public void ConnectNodeVector(NodeVector poNodeVector)
		{
			int iIndex = 0;
			foreach(Node oNode in oNodes)
			{
				oNode.Net.Connect(poNodeVector[iIndex].Net);
				iIndex++;
			}
		}

		public void ConnectNode(int piIndex, Node poNode)
		{
			Node oNode = (Node)oNodes[piIndex];
			oNode.Net.Connect(poNode.Net);
		}

		public void SimulationDestabilize()
		{
		}

		public string NodeVectorAsString
		{
			get
			{
				string sVector = "";
				foreach(Node oNode in oNodes)
				{
					sVector = sVector + oNode.NodeStateAsChar;
				}
				return sVector;
			}

			set
			{
				int iStringSize = value.Length;
				int iNodeIndex = 0;

				foreach(Node oNode in oNodes)
				{
					if(iNodeIndex < iStringSize)
						oNode.NodeStateAsChar = value[iNodeIndex];
					else
						oNode.NodeState = NodeState.Undefined;
					iNodeIndex ++;
				}
			}
		}

		public override string ToString()
		{
			return this.NodeVectorAsString;
		}

		public string HirarchicalName
		{
			get {return oParentComponent.HirarchicalName + "." + this.Name;}
		}

		/*public void ParseNetStructure()
		{
			oParentComponent.ComponentVerilog.VerilogTraceLog("------  Start Parsing Net Structure -----",this);
			foreach(Node oNode in oNodes)
			{
				oNode.ParseNetStructure();
			}			
		}*/

		public NodeStructure OrganizeNodeStructure()
		{
			eNodeStructure = NodeStructure.Unknown;

			foreach(Node oNode in oNodes)
			{
				if (eNodeStructure == NodeStructure.Unknown)
					eNodeStructure = oNode.OrganizeNodeStructure();
				else
				{
					if (eNodeStructure != oNode.OrganizeNodeStructure())
						eNodeStructure = NodeStructure.Mixed;
				}
				oParentComponent.ComponentVerilog.VerilogTraceLog("Classified Node",oNode);
			}
			return eNodeStructure;
		}

		internal NodeStructure NodeStructure
		{
			get{return eNodeStructure;}
			set{eNodeStructure = value;}
		}

		public string GetLogIdString(LogType peLogType)
		{
			string sDebug = "{NodeVector: " + HirarchicalName + " [";
			if (peLogType == LogType.VerilogTrace)
			{
				sDebug += "NodeFlowType=" + NodeFlowType.ToString();
				sDebug += ",Size=" + Size.ToString();
				sDebug += ",NodeStructure=" + eNodeStructure.ToString();
			}
			sDebug +="]}";
			return sDebug;
		}
	}
}
